﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using TpsAutoSurvey_PDA_Version_.RealizedClasses;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json;
using System.Threading;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace TpsAutoSurvey_PDA_Version_.SocketModule
{


    public class PdaClient
    {

        TcpClient tcpClient;

        //Socket Client;
        Timer t = null;
        NetworkStream stream;
        public string name;
        public int TimeInterval = 1000 * 30;
        public int port = Convert.ToInt32(ToolClass.GetProfileString("tcp_port"));
        public string ipAdress = ToolClass.GetProfileString("tcp_ip");  //"169.254.2.2";//
        byte[] myReadBuffer = new byte[1024];
        public delegate void MessageCome(SendData data);
        public delegate void SurveyTimeUp();
        public SurveyTimeUp OnSurveyTimeUp;
        public MessageCome OnMessageCome;
        private int HttpConnectInterval = 0;


      
        public PdaClient()
        {
            this.tcpClient = new TcpClient();
            name = ToolClass.GetProfileString("pdaName");
            connect();
            t = new Timer(new TimerCallback(t_Tick), null, TimeInterval, TimeInterval);
            this.EnableTimer = false;
            this.invokeTimes = ToolClass.ReadTimerList();
          
        }
        private bool _isWorking = false;
        public bool IsWorking
        {
            get { return this._isWorking; }
            set
            {
                this._isWorking = value;
            }
        }
        void t_Tick(object sender)
        {
           
            if (IsWorking == false)
            {
                Send("&");
                if (this.EnableTimer == true)
                {
                    CheckTimeUpForSurvey();
                }
            }
            HttpConnectInterval++;
            //一段时间后维持网络连接
            if (HttpConnectInterval > 10)
            {
                new Thread(new ThreadStart(() => ConnectToWeb())).Start();
                this.HttpConnectInterval = 0;
            }

        }
        #region Send
        public void SendJson(SendData data)
        {
            string dataStr = JsonConvert.SerializeObject(data);
            Send(dataStr);
            Thread.Sleep(100);
        }


        public void Send(string msg)
        {
            if (this.tcpClient.Client == null || this.tcpClient.Client.Connected == false)
            {
                connect();
                return;
            }
            byte[] sendbyte =Encoding.UTF8.GetBytes(msg);
            try
            {
                lock (stream)
                {
                    IAsyncResult re = stream.BeginWrite(sendbyte, 0, sendbyte.Length, new AsyncCallback(SendCallback), stream);
                }
            }
            catch
            {
                connect();
            }
        }
        private void SendCallback(IAsyncResult ar)
        {
            try
            {
                lock (stream)
                {
                    stream.EndWrite(ar);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Send Tcp Err:" + e.ToString());
            }
        }
        #endregion
        #region Connect
        private bool ConnectToWeb()
        {
            HttpWebRequest hwrRequest;
            HttpWebResponse hwrResponse;
            bool connect = false;
            string strUrl = @"http://wap.baidu.com/";
            try
            {
                hwrRequest = (HttpWebRequest)WebRequest.Create(strUrl);
                hwrRequest.Timeout = 10 * 1000;
                hwrResponse = (HttpWebResponse)hwrRequest.GetResponse();

                if (hwrResponse.StatusCode == HttpStatusCode.OK)
                {
                    connect = true;
                }
                else
                {
                    connect = false;
                }
                hwrResponse.Close();
                return connect;
            }
            catch
            {
                return false;
            }
        }

        void connect()
        {
            try
            {
                try
                {
                    this.tcpClient.GetStream().Close();
                    this.tcpClient.Close();
                }
                catch
                {

                }
                this.tcpClient = new TcpClient();
                IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(ipAdress), port);
                lock (tcpClient)
                {
                    tcpClient.Connect(ipep);
                }
                this.stream = tcpClient.GetStream();
                GetRead();//启动读取数据的进程
                var sd = new SendData();
                sd.Header = "Register";
                sd.Data.Para = name;
                SendJson(sd);
            }
            catch (Exception a)
            {
                ToolClass.Log("Connect Err: " + a.Message);
                this.tcpClient = new TcpClient();
                if (ConnectToWeb() == false)
                {
                    System.Windows.Forms.Application.Exit();
                }
                return;
            }
        }
        #endregion
        #region Read
        void GetRead()
        {
            try
            {
                myReadBuffer = new byte[400];
                lock (stream)
                {
                    stream.BeginRead(myReadBuffer, 0, myReadBuffer.Length, new AsyncCallback(myReadCallBack), null);
                }
            }
            catch (Exception a)
            {
                ToolClass.Log("Read Err: " + a.Message);
            }
        }
        private void myReadCallBack(IAsyncResult ar)
        {

            try
            {
                int length = 0;
                lock (stream)
                {
                    length = this.stream.EndRead(ar);   
                }
                if (length > 0)
                {
                    string str = Encoding.UTF8.GetString(myReadBuffer, 0, length);
                    if (OnMessageCome != null)
                    {
                        ToolClass.LogNetWorkStatus();//记录最新通讯的时间
                        if (str != "&")
                        {
                            try
                            {
                                SendData data = JsonConvert.DeserializeObject<SendData>(str);
                                if (data != null)
                                {
                                    OnMessageCome(data);

                                }
                            }
                            catch(Exception a)
                            {
                                ToolClass.Log("Erro on deserialize json string:  " + a.Message);
                            }
                        }
                    }
                    GetRead();
                }
                else
                {
                    this.tcpClient.GetStream().Close();
                    this.tcpClient.Close();
                }
            }
            catch(Exception a)
            {
                
                ToolClass.Log("Err on recive,stop recive:" + a.Message);
                this.tcpClient.GetStream().Close();
                this.tcpClient.Close();
                //Process.GetCurrentProcess().Kill();
                return;
            }


        }
        #endregion
        #region Survey Time Up
        public bool EnableTimer { get; set; }

        public List<DateTime> invokeTimes;
        private void CheckTimeUpForSurvey()
        {
            foreach (var time in this.invokeTimes)
            {
                if (ShouldTimerInvoke(time))
                {
                    if (this.OnSurveyTimeUp != null)
                    {
                        OnSurveyTimeUp();
                        ToolClass.Log("Time For Survey!!!");
                        this.IsWorking = true;
                    }
                }
            }
        }

        private bool ShouldTimerInvoke(DateTime time)
        {
            var now = DateTime.Now;
            if (now.Hour == time.Hour && now.Minute == time.Minute)
            {
                return true;
            }
            else
            {
                return false;
            }

        }
        #endregion
    }
}
